package com.sunny.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Created by Sunny on 2016/4/21.
 */
public class BeanUtils {

    protected static Logger logger = LoggerFactory.getLogger(BeanUtils.class);
    /**
     * 直接读取对象属性值,无视private/protected修饰符,不经过getter函数.
     */
    public static Object getFieldValue(Object object, String fieldName)
            throws NoSuchFieldException
    {
        Field field = getDeclaredField(object, fieldName);
        if (!field.isAccessible())
        {
            field.setAccessible(true);
        }

        Object result = null;
        try
        {
            result = field.get(object);
        }
        catch (IllegalAccessException e)
        {
            logger.error("不可能抛出的异常{}", e.getMessage());
        }
        return result;
    }


    /**
     * 循环向上转型,获取对象的DeclaredField.
     */
    public static Field getDeclaredField(Object object, String fieldName)
            throws NoSuchFieldException
    {
        Assert.notNull(object);
        return getDeclaredField(object.getClass(), fieldName);
    }

    //Logger
    public static Class getSuperClassGenricType(final Class clazz, final int index)
    {

        Type genType = clazz.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType))
        {
        //    logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType)genType).getActualTypeArguments();

        if (index >= params.length || index < 0)
        {
         //   logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
         //           + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class))
        {
        //    logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }

        return (Class)params[index];
    }
}
